package com.digicom.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.digicom.common.constant.Constants;
import com.digicom.common.entity.User;
import com.digicom.common.exception.ServiceException;
import com.digicom.common.mapper.UserMapper;
import com.digicom.common.utils.JwtUtil;
import com.digicom.service.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public String login(String username, String password, String clientType) {
        // 参数校验
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            throw new ServiceException("用户名/密码不能为空");
        }

        // 查询用户信息
        User user = userMapper.selectByUsername(username);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 判断用户状态
        if (Constants.USER_STATUS_DISABLED.equals(user.getStatus())) {
            throw new ServiceException("用户已被禁用");
        }

        // 校验密码
        if (!password.equals(user.getPassword())) {
            // 实际项目中应使用加密后的密码进行比对
            throw new ServiceException("密码错误");
        }

        // 更新登录信息
        user.setLoginDate(new Date());
        // 这里应该设置登录IP，实际项目中可从请求中获取
        // user.setLoginIp(IpUtil.getIpAddr(ServletUtils.getRequest()));
        updateById(user);

        // 生成token并返回
        return generateToken(user);
    }

    @Override
    public String loginByMobile(String mobile, String code, String clientType) {
        // 参数校验
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(code)) {
            throw new ServiceException("手机号/验证码不能为空");
        }

        // 校验验证码
        // 实际项目中应从Redis或其他存储中获取验证码进行校验
        // String cacheCode = redisTemplate.opsForValue().get("SMS_CODE:" + mobile);
        // if (!code.equals(cacheCode)) {
        //     throw new ServiceException("验证码错误");
        // }

        // 查询用户信息
        User user = userMapper.selectByMobile(mobile);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 判断用户状态
        if (Constants.USER_STATUS_DISABLED.equals(user.getStatus())) {
            throw new ServiceException("用户已被禁用");
        }

        // 更新登录信息
        user.setLoginDate(new Date());
        updateById(user);

        // 生成token并返回
        return generateToken(user);
    }

    @Override
    public String loginByWechat(String wxCode, String clientType) {
        // 参数校验
        if (StringUtils.isBlank(wxCode)) {
            throw new ServiceException("微信授权码不能为空");
        }

        // 调用微信接口获取openId
        // 实际项目中应调用微信API获取openId和unionId
        String openId = "mock-openid-" + wxCode;  // 模拟获取openId
        
        // 查询用户信息
        User user = userMapper.selectByWxOpenId(openId);
        
        // 用户不存在则自动注册
        if (user == null) {
            user = new User();
            user.setWxOpenId(openId);
            user.setNickname("微信用户");  // 实际应从微信获取用户昵称
            user.setUserType(Constants.USER_TYPE_NORMAL);
            user.setStatus(Constants.USER_STATUS_NORMAL);
            save(user);
        } else if (Constants.USER_STATUS_DISABLED.equals(user.getStatus())) {
            throw new ServiceException("用户已被禁用");
        }

        // 更新登录信息
        user.setLoginDate(new Date());
        updateById(user);

        // 生成token并返回
        return generateToken(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(User user, String code) {
        // 参数校验
        if (user == null || StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) {
            throw new ServiceException("注册信息不完整");
        }

        if (StringUtils.isNotBlank(user.getMobile())) {
            // 校验验证码
            // 实际项目中应从Redis或其他存储中获取验证码进行校验
            // String cacheCode = redisTemplate.opsForValue().get("SMS_CODE:" + user.getMobile());
            // if (!code.equals(cacheCode)) {
            //     throw new ServiceException("验证码错误");
            // }
            
            // 判断手机号是否已被注册
            if (userMapper.selectByMobile(user.getMobile()) != null) {
                throw new ServiceException("手机号已被注册");
            }
        }

        // 判断用户名是否已被注册
        if (userMapper.selectByUsername(user.getUsername()) != null) {
            throw new ServiceException("用户名已被注册");
        }

        // 设置用户默认信息
        user.setUserType(Constants.USER_TYPE_NORMAL);
        user.setStatus(Constants.USER_STATUS_NORMAL);
        
        // 实际项目中应对密码进行加密处理
        // user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 保存用户信息
        return save(user);
    }

    @Override
    public User getUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public User getUserByMobile(String mobile) {
        return userMapper.selectByMobile(mobile);
    }

    @Override
    public User getUserByWxOpenId(String wxOpenId) {
        return userMapper.selectByWxOpenId(wxOpenId);
    }

    @Override
    public Page<User> listUserPage(User user, Page<User> page) {
        return userMapper.selectUserPage(page, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(Long userId, String newPassword) {
        if (userId == null || StringUtils.isBlank(newPassword)) {
            throw new ServiceException("参数不能为空");
        }

        User user = getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        // 实际项目中应对新密码进行加密处理
        // newPassword = passwordEncoder.encode(newPassword);
        
        user.setPassword(newPassword);
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changeStatus(Long userId, String status) {
        if (userId == null || StringUtils.isBlank(status)) {
            throw new ServiceException("参数不能为空");
        }

        User user = getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        user.setStatus(status);
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changeUserType(Long userId, String userType) {
        if (userId == null || StringUtils.isBlank(userType)) {
            throw new ServiceException("参数不能为空");
        }

        User user = getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }

        user.setUserType(userType);
        return updateById(user);
    }

    /**
     * 生成token
     *
     * @param user 用户信息
     * @return token
     */
    private String generateToken(User user) {
        // 创建用户token信息
        Map<String, Object> claims = new HashMap<>(8);
        claims.put("user_id", user.getUserId());
        claims.put("username", user.getUsername());
        claims.put("user_type", user.getUserType());
        
        // 生成token
        String token = JwtUtil.createToken(claims);
        
        // 将用户信息存入Redis，设置过期时间
        String userKey = Constants.LOGIN_USER_KEY + ":" + user.getUserId();
        redisTemplate.opsForValue().set(userKey, user, Constants.EXPIRATION, TimeUnit.SECONDS);
        
        return token;
    }
} 